SPB Git
1.9 KB · 25 lines typescript
1import { guarded, json } from "@/lib/api";2import { getConversation, getActiveMessages } from "@/lib/chat/store";3import type { Part } from "@/lib/ai/types";45export const GET = guarded<{ id: string }>(async (req, { params }) => {6  const conv = await getConversation(params.id);7  if (!conv) return json({ error: "Introuvable" }, { status: 404 });8  const messages = await getActiveMessages(params.id);9  const fmt = req.nextUrl.searchParams.get("format") ?? "md";10  const safe = conv.title.replace(/[^\w\- àâçéèêëîïôûùüÿœ]/gi, "_").slice(0, 60);11  if (fmt === "json") return new Response(JSON.stringify({ conversation: conv, messages }, null, 2), { headers: { "content-type": "application/json", "content-disposition": `attachment; filename="${safe}.json"` } });12  const lines = [`# ${conv.title}`, "", `_Exporté le ${new Date().toLocaleString("fr-CA")} — ${messages.length} messages_`, ""];13  for (const m of messages) {14    lines.push(`## ${m.role === "user" ? "Vous" : `Assistant${m.model_id ? ` (${m.model_id})` : ""}`}`, "");15    for (const p of m.parts as Part[]) {16      if (p.type === "text") lines.push(p.text, "");17      else if (p.type === "tool_call") lines.push(`> 🔧 ${p.name}(${JSON.stringify(p.input)}) → ${p.status}`, "");18      else if (p.type === "file" || p.type === "image") lines.push(`> 📎 ${"name" in p ? p.name : p.attachmentId}`, "");19      else if (p.type === "generated_image") lines.push(`> 🖼️ image générée (${p.model}) : ${p.prompt}`, "");20    }21    if (m.role === "assistant" && m.usage) lines.push(`<sub>${m.usage.input} → ${m.usage.output} jetons · ${m.cost_usd != null ? `$${Number(m.cost_usd).toFixed(4)}` : "coût inconnu"} · ${m.latency_ms} ms</sub>`, "");22  }23  return new Response(lines.join("\n"), { headers: { "content-type": "text/markdown; charset=utf-8", "content-disposition": `attachment; filename="${safe}.md"` } });24});25
Files · main
Menu

Theme